# from collections import Iterable
from typing import Iterable

import torch
from numpy import ndarray
from torch import tensor

#功能：类型判断，类型转换；
def typeof(variate):
    """功能：判断变量类型的函数；
    返回：类型字符串
    注意：均是可迭代类型
    """
    type1 = ""
    if type(variate) == type(1):
        type1 = "int"
    elif type(variate) == type("str"):
        type1 = "str"
    elif type(variate) == type(12.3):
        type1 = "float"
    elif type(variate) == type([1]):
        type1 = "list"
    elif type(variate) == type(()):
        type1 = "tuple"
    elif type(variate) == type({"key1":"123"}):
        type1 = "dict"
    elif type(variate) == type({"key1"}):
        type1 = "set"
    return type1


def get_chi_Type(variate):
    """功能：判断变量类型的函数；
    返会：类型中文字符串;
    调用：
        money=120
        print("{0}是{1}".format(money,get_chi_Type(money)))
    """
    arr = {"int":"整数","float":"浮点","str":"字符串","list":"列表","tuple":"元组","dict":"字典","set":"集合"}
    vartype = typeof(variate)
    if not (vartype in arr):
        return "未知类型"
    return arr[vartype]


def judge_tpye(data,sup):
    """功能：数据类型判断-是否为指定类型；
    data:对象；
    sup=[list,tuple, dict]；指定的数据类型
    """
    if type(data) in sup:  # type() 不会认为子类是一种父类类型，不考虑继承关系#isinstance() 会认为子类是一种父类类型，考虑继承关系
        return True
    else:
        print("error不在支持的数据类型是：",sup)
        return False


def get_variable_name(variable,loc=locals()):
    """功能：取变量名（而非变量值）#取等式左边名称
    思路：# loc = locals()#返回当前本地符号表的字典（方法并不多，应用范围也不多）
    调用：
    hello = 123
    print(get_variable_name(hello))
    """
    for k,v in loc.items():#遍历挺费事
        # print(k)#
        if loc[k] ==variable:
            return k


def print_var_len_shape(v):
    """
    功能：变量类型与形状打印
    调用：
    t=tensor([1])
    print_var_len_shape(1)
    """
    from numpy import ndarray
    if type(v) in [list,dict,tuple,str]:#len()形状类型
        print(f"{type(v)},len={len(v)}")
    elif type(v) in [int,float]:#无len()和shape
        print(f"{type(v)},{v}")
    elif type(v) in [torch.Tensor]:
        print(f"{type(v)},shape={v.shape},device={v.device},dtype={v.dtype}")
    elif type(v) in [ndarray]:#AttributeError: 'numpy.ndarray' object has no attribute 'device'
        print(f"{type(v)},shape={v.shape},dtype={v.dtype}")
    else:#各种不同的类类型-object of type 'BertModel' has no len()
        print(f"{type(v)}")
    return type(v)
# t=tensor([1])
# print_var_len_shape(t)


def sci_sparse2sparse_tensor(sparse_data):
    """功能：稀疏矩阵转换：scipy.sparse.coo_matrix-》torch.sparse_coo_tensor"""
    import scipy.sparse
    import torch
    #较好的转换方向[array]->np.array->torch.tensor
    #UserWarning: Creating a tensor from a list of numpy.ndarrays is extremely slow. Please consider converting the
    # list to a single numpy.ndarray with numpy.array() before converting to a tensor.
    # 创建一个SciPy稀疏矩阵
    # sparse_matrix = scipy.sparse.coo_matrix([[0, 1, 0], [2, 0, 3], [0, 4, 0]])
    # print(sparse_matrix.row,sparse_matrix.col)
    # 将SciPy稀疏矩阵转换为PyTorch稀疏张量
    # indices = torch.LongTensor([sparse_matrix.row, sparse_matrix.col])
    # values = torch.FloatTensor(sparse_matrix.data)
    # size = torch.Size(sparse_matrix.shape)
    # sparse_tensor = torch.sparse_coo_tensor(indices, values, size)
    coo_tensor = torch.sparse_coo_tensor(torch.LongTensor([sparse_data.row, sparse_data.col]),
                                         torch.FloatTensor(sparse_data.data), sparse_data.shape)
    # print(sparse_tensor)
    return coo_tensor


def sci_sparse2sparse_tensor(sp1):
    """功能：scipy.sparse（仅可用cpu）-》coo_matrix-》sparse_coo_tensor（可用gpu）
    """
    import scipy
    sparse_data = scipy.sparse.coo_matrix(sp1)#scipy.sparse-》coo_matrix
    # coo_matrix-》sparse_coo_tensor
    coo_tensor = torch.sparse_coo_tensor(torch.LongTensor([sparse_data.row, sparse_data.col]),
                                                torch.FloatTensor(sparse_data.data), sparse_data.shape)
    return coo_tensor